import { Injectable } from '@nestjs/common';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { Repository, Between, DataSource } from 'typeorm';
import { LogArticleEntity } from './log-article.entity';
import { LogSurveyEntity } from './log-survey.entity';
import { ArticleContentEntity, ArticleContentType } from '../article/article-content/article-content.entity';
import { SurveyType } from '../survey/survey.entity';
import dayjs from 'dayjs';
import { UserEntity } from '../user/user.entity';
import { UserWechatEntity } from '../user/user-wechat/user-wechat.entity';
import { CategoryEntity } from '../category/category.entity';

@Injectable()
export class LogService {
  constructor(
    @InjectRepository(LogArticleEntity)
    private readonly logArticleRepository: Repository<LogArticleEntity>,
    @InjectRepository(LogSurveyEntity)
    private readonly logSurveyRepository: Repository<LogSurveyEntity>,
    @InjectDataSource()
    private readonly datasource: DataSource
  ) {}

  /**
   * 保存文章阅读日志
   * @param articleId 文章ID
   * @param userId 用户ID
   * @param articleType 文章类型
   * @param readDuration 阅读时长（秒）
   * @param categoryId 分类ID（可选）
   * @returns 保存的日志实体
   */
  async saveArticleLog(
    articleId: number,
    userId: number,
    articleType: ArticleContentType,
    readDuration: number,
    categoryId?: number
  ): Promise<LogArticleEntity> {
    const articleLog = this.logArticleRepository.create({
      articleId,
      userId,
      articleType,
      readDuration,
      categoryId,
    });

    return await this.logArticleRepository.save(articleLog);
  }

  /**
   * 保存问卷调查日志
   * @param surveyId 问卷ID
   * @param userId 用户ID
   * @param isFinish 是否完成问卷
   * @param duration 完成时长（秒）
   * @param score 问卷得分
   * @param answers 用户回答的JSON字符串
   * @param surveyType 问卷类型
   * @returns 保存的日志实体
   */
  async saveSurveyLog(
    surveyId: string,
    userId: number,
    isFinish: number = 1,
    duration: number = 0,
    score: number = 0,
    answers: string = '{}',
    surveyType: SurveyType = SurveyType.SURVEY
  ): Promise<LogSurveyEntity> {
    const surveyLog = this.logSurveyRepository.create({
      surveyId,
      userId,
      isFinish,
      duration,
      score,
      answers,
      surveyType,
    });

    return await this.logSurveyRepository.save(surveyLog);
  }

  /**
   * 获取今日或昨日的阅读量统计
   * @returns [今日阅读量, 昨日阅读量]
   */
  async getTodayOrLastdayReadingCount(): Promise<[number, number]> {
    const todayStart = new Date(dayjs().format('YYYY-MM-DD 00:00:00'));
    const todayEnd = new Date(dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'));
    const yesterdayStart = new Date(dayjs().subtract(1, 'day').format('YYYY-MM-DD 00:00:00'));
    const yesterdayEnd = new Date(dayjs().format('YYYY-MM-DD 00:00:00'));

    // 查询今日阅读量
    const todayCount = await this.logArticleRepository.count({
      where: {
        createdAt: Between(todayStart, todayEnd),
      },
    });

    // 查询昨日阅读量
    const yesterdayCount = await this.logArticleRepository.count({
      where: {
        createdAt: Between(yesterdayStart, yesterdayEnd),
      },
    });

    return [todayCount, yesterdayCount];
  }

  /**
   * 获取今日或昨日的答题次数统计
   * @returns [今日答题次数, 昨日答题次数]
   */
  async getTodayOrLastdayQuizCount(): Promise<[number, number]> {
    const todayStart = new Date(dayjs().format('YYYY-MM-DD 00:00:00'));
    const todayEnd = new Date(dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'));
    const yesterdayStart = new Date(dayjs().subtract(1, 'day').format('YYYY-MM-DD 00:00:00'));
    const yesterdayEnd = new Date(dayjs().format('YYYY-MM-DD 00:00:00'));

    // 查询今日阅读量
    const todayCount = await this.logSurveyRepository.count({
      where: {
        createdAt: Between(todayStart, todayEnd),
        surveyType: SurveyType.QUIZ,
      },
    });

    // 查询昨日阅读量
    const yesterdayCount = await this.logSurveyRepository.count({
      where: {
        createdAt: Between(yesterdayStart, yesterdayEnd),
        surveyType: SurveyType.QUIZ,
      },
    });

    return [todayCount, yesterdayCount];
  }

  async calcCurrentQuizCorrectRate(list: LogSurveyEntity[]): Promise<number> {
    if (list.length === 0) {
      return 0;
    }

    const correctCount = list
      .map((item) => {
        let answers = { correct: 0 };

        try {
          answers = JSON.parse(item.answers);
        } catch (error) {
          answers = { correct: 0 };
        }

        return answers?.correct ?? 0;
      })
      .reduce((acc, curr) => {
        return acc + curr;
      }, 0);

    return correctCount / (list.length * 20);
  }

  async getTodayOrLastdayQuizScore(): Promise<[number, number]> {
    const todayStart = new Date(dayjs().format('YYYY-MM-DD 00:00:00'));
    const todayEnd = new Date(dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'));
    const yesterdayStart = new Date(dayjs().subtract(1, 'day').format('YYYY-MM-DD 00:00:00'));
    const yesterdayEnd = new Date(dayjs().format('YYYY-MM-DD 00:00:00'));

    // 查询今日答题得分
    const todayList = await this.logSurveyRepository.find({
      where: {
        createdAt: Between(todayStart, todayEnd),
        surveyType: SurveyType.QUIZ,
      },
    });

    const todayCorrectRate = await this.calcCurrentQuizCorrectRate(todayList);

    // 查询昨日答题得分
    const yesterdayList = await this.logSurveyRepository.find({
      where: {
        createdAt: Between(yesterdayStart, yesterdayEnd),
        surveyType: SurveyType.QUIZ,
      },
    });

    const yesterdayCorrectRate = await this.calcCurrentQuizCorrectRate(yesterdayList);

    console.log([todayCorrectRate, yesterdayCorrectRate]);

    return [todayCorrectRate, yesterdayCorrectRate];
  }

  /**
   * 获取用户的阅读量统计
   * @param userId 用户ID
   * @returns [今日阅读量, 总阅读量]
   */
  async getUserReadingCount(userId: number): Promise<[number, number]> {
    const todayStart = new Date(dayjs().format('YYYY-MM-DD 00:00:00'));
    const todayEnd = new Date(dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'));

    // 查询今日阅读量
    const todayCount = await this.logArticleRepository.count({
      where: {
        userId,
        createdAt: Between(todayStart, todayEnd),
      },
    });

    // 查询总阅读量
    const totalCount = await this.logArticleRepository.count({
      where: {
        userId,
      },
    });

    return [todayCount, totalCount];
  }

  /**
   * 获取用户的答题统计
   * @param userId 用户ID
   * @returns [今日答题次数, 总答题次数, 今日答题正确率, 总答题正确率]
   */
  async getUserQuizStats(userId: number): Promise<[number, number, number, number, number]> {
    const todayStart = new Date(dayjs().format('YYYY-MM-DD 00:00:00'));
    const todayEnd = new Date(dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'));

    // 查询今日答题次数
    const todayCount = await this.logSurveyRepository.count({
      where: {
        userId,
        createdAt: Between(todayStart, todayEnd),
        surveyType: SurveyType.QUIZ,
      },
    });

    // 查询总答题次数
    const totalCount = await this.logSurveyRepository.count({
      where: {
        userId,
        surveyType: SurveyType.QUIZ,
      },
    });

    // 查询今日答题记录
    const todayQuizList = await this.logSurveyRepository.find({
      where: {
        userId,
        createdAt: Between(todayStart, todayEnd),
        surveyType: SurveyType.QUIZ,
      },
    });

    // 查询总答题记录
    const totalQuizList = await this.logSurveyRepository.find({
      where: {
        userId,
        surveyType: SurveyType.QUIZ,
      },
    });

    // 计算今日答题正确率
    const todayCorrectRate = await this.calcCurrentQuizCorrectRate(todayQuizList);

    // 计算总答题正确率
    const totalCorrectRate = await this.calcCurrentQuizCorrectRate(totalQuizList);

		// 获取答题正确率最高的记录
		const topCorrectRate = totalQuizList.length > 0
			? Math.max(...totalQuizList.map(item => {
					let answers = { correct: 0 };
					try {
						answers = JSON.parse(item.answers);
					} catch (error) {
						answers = { correct: 0 };
					}
					return answers.correct / 20; // 每题20分
				}))
			: 0;

    return [todayCount, totalCount, todayCorrectRate, totalCorrectRate, topCorrectRate];
  }

  /**
   * 获取用户的平均阅读时长
   * @param userId 用户ID
   * @returns [今日平均阅读时长(秒), 总体平均阅读时长(秒)]
   */
  async getUserAverageReadingDuration(userId: number): Promise<[number, number]> {
    const todayStart = new Date(dayjs().format('YYYY-MM-DD 00:00:00'));
    const todayEnd = new Date(dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'));

    // 查询今日阅读记录
    const todayReadingLogs = await this.logArticleRepository.find({
      where: {
        userId,
        createdAt: Between(todayStart, todayEnd),
      },
    });

    // 查询总阅读记录
    const totalReadingLogs = await this.logArticleRepository.find({
      where: {
        userId,
      },
    });

    // 计算今日平均阅读时长
    const todayTotalDuration = todayReadingLogs.reduce(
      (sum, log) => sum + (log.readDuration || 0),
      0
    );
    const todayAverageDuration =
      todayReadingLogs.length > 0 ? Math.round(todayTotalDuration / todayReadingLogs.length) : 0;

    // 计算总体平均阅读时长
    const totalDuration = totalReadingLogs.reduce((sum, log) => sum + (log.readDuration || 0), 0);
    const totalAverageDuration =
      totalReadingLogs.length > 0 ? Math.round(totalDuration / totalReadingLogs.length) : 0;

    return [todayAverageDuration, totalAverageDuration];
  }

  /**
   * 获取文章的阅读时长统计
   * @param articleId 文章ID
   * @returns [总阅读时长(秒), 平均阅读时长(秒), 阅读次数]
   */
  async getArticleReadingStats(articleId: number): Promise<[number, number, number]> {
    // 查询该文章的所有阅读记录
    const readingLogs = await this.logArticleRepository.find({
      where: {
        articleId,
      },
    });

    // 计算阅读次数
    const readCount = readingLogs.length;

    if (readCount === 0) {
      return [0, 0, 0];
    }

    // 计算总阅读时长
    const totalDuration: number = readingLogs.reduce(
      (sum, log) => sum + (log.readDuration || 0),
      0
    );

    // 计算平均阅读时长
    const averageDuration = Math.round(totalDuration / readCount);

    return [totalDuration, averageDuration, readCount];
  }

  async getAllArticleLogs(): Promise<Record<string, any>[]> {
    return await this.datasource
      .createQueryBuilder()
      .select('article_log.id', 'id')
      .addSelect('article_log.created_at', 'createdAt')
      .addSelect('article_log.article_id', 'articleId')
      .addSelect('article_log.read_duration', 'readDuration')
      .addSelect('userWechat.nickname', 'nickname')
      .addSelect('userWechat.phone', 'phone')
			.addSelect('articleContent.code', 'articleCode')
			.addSelect('articleContent.name', 'articleName')
			.addSelect('articleContent.author', 'articleAuthor')
			.addSelect('articleContent.type', 'articleType')
			.addSelect('category.name', 'articleCategoryName')
      .from(LogArticleEntity, 'article_log')
      .leftJoin(UserEntity, 'user', 'user.id = article_log.userId')
      .leftJoin(UserWechatEntity, 'userWechat', 'userWechat.id = user.wechat_id')
			.leftJoin(ArticleContentEntity, 'articleContent', 'articleContent.id = article_log.article_id')
			.leftJoin(CategoryEntity, 'category', 'category.id = article_log.category_id')
      .orderBy('article_log.id', 'DESC')
      .getRawMany();
  }
}
